package security;

/**
 * @projectName: java-sample
 * @description:
 * @author: Adam
 * @create: 2019-12-31 18:55
 **/

import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 消息摘要（Message Digest）又称为数字摘要(Digital Digest)
 * 它是一个唯一对应一个消息或文本的固定长度的值，它由一个单向Hash加密函数对消息进行作用而产生
 * 特点：
 * 无论输入的消息有多长，计算出来的消息摘要的长度总是固定的。例如应用MD5算法摘要的消息有128个比特位，用SHA-1算法摘要的消息最终有160比特位的输出
 *
 * 只要输入的消息不同，对其进行摘要以后产生的摘要消息也必不相同；但相同的输入必会产生相同的输出
 * 消息摘要是单向、不可逆的
 *
 * 常见算法 :
 * MD5
 * SHA1
 * SHA256
 * SHA512
 */

public class DigesDemo {

    /**
     * MD5算法 : 摘要结果16个字节, 转16进制后32个字节
     * SHA1算法 : 摘要结果20个字节, 转16进制后40个字节
     * SHA256算法 : 摘要结果32个字节, 转16进制后64个字节
     * SHA512算法 : 摘要结果64个字节, 转16进制后128个字节
     */
    public static void main(String[] args) throws Exception{
        String input = "aa";

        String md5 = getDigestFile("MD5", "a.pri");
        System.out.println(md5);

        String sha1 = getDigestFile("SHA-1", "a.pri");
        System.out.println(sha1);

        String sha256 = getDigestFile("SHA-256", "a.pri");
        System.out.println(sha256);

        String sha512 = getDigestFile("SHA-512", "a.pri");
        System.out.println(sha512);

    }

    /**
      * 获取字符串的消息摘要
      * @author jie
      * @param algorithm 算法
      * @param input 原文
      * @return 消息摘要
      * @date 2019/12/31 18:58
      */
    public static String getDigest(String algorithm,String input) throws NoSuchAlgorithmException {
        //获取信息摘要对象
        MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
        //获取消息摘要
        byte[] digest = messageDigest.digest(input.getBytes());
        return toHex(digest);

    }


    /**
      * 获取文件的消息摘要
      * @author jie
      * @param
      * @return
      * @date 2019/12/31 19:07
      */
    private static String getDigestFile(String algorithm,String filePath) throws IOException, NoSuchAlgorithmException {

        FileInputStream fis = new FileInputStream(filePath);
        int len;
        byte[] buffer = new byte[1024];
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        while ((len=fis.read(buffer))!=-1){
            baos.write(buffer, 0, len);
        }
        // 获取消息摘要对象
        MessageDigest md = MessageDigest.getInstance(algorithm);
        // 获取消息摘要
        byte[] digest = md.digest(baos.toByteArray());
        return toHex(digest);
    }
    
    
    /**
      * 
      * @author jie
      * @param
      * @return 
      * @date 2019/12/31 19:02
      */
    private static String toHex(byte[] digest){
        StringBuilder sb = new StringBuilder();
        for(byte b:digest){
            //转为16进制数据
            int i = b & 0xff;
            String hex = Integer.toHexString(i);
            //如果长度为1，前面补0
            if (hex.length()==1){
                hex = 0 + hex;
            }
            sb.append(hex);
        }
        return sb.toString();
    }
}
